﻿//***********************************************************************************
// 文件名称：PlayerManager
// 功能描述：玩家管理类
// 数据表：
// 作者：liuxiaohu
// 日期：2017/3/13 9:15:20
// 修改记录：
//***********************************************************************************

using System;
using System.Threading;
using System.Collections.Generic;

namespace GameServer
{
    using MySql.Data.MySqlClient;

    /// <summary>
    /// 玩家管理类
    /// </summary>
    public class PlayerManager
    {
        #region 字段

        /// <summary>
        /// 玩家列表
        /// </summary>
        private Dictionary<Int32, Player> playerList = new Dictionary<Int32, Player>();

        /// <summary>
        /// 同步读写锁对象
        /// </summary>
        private static ReaderWriterLockSlim playerListLock = new ReaderWriterLockSlim();

        /// <summary>
        /// 玩家数据库对象
        /// </summary>
        private PlayerDB playerDB = new PlayerDB();

        /// <summary>
        /// 错误信息
        /// </summary>
        private String errorMessage;

        #endregion

        #region 方法

        /// <summary>
        /// 初始化，从数据库加载玩家数据
        /// </summary>
        public bool Init()
        {
            playerList = playerDB.GetList();

            return true;
        }

        /// <summary>
        /// 获取玩家列表
        /// </summary>
        /// <param name="isWritting">是否有写操作</param>
        /// <returns>玩家列表</returns>
        public Dictionary<Int32, Player> GetPlayerList(Boolean isWritting = true)
        {
            Dictionary<Int32, Player> tmpPlayerList = new Dictionary<int, Player>();

            // 不存在写操作时直接从内存中加载数据
            if (!isWritting)
            {
                tmpPlayerList = playerList;
            }
            else
            {
                playerListLock.EnterReadLock();

                try
                {
                    foreach (var player in playerList)
                    {
                        tmpPlayerList.Add(player.Key, player.Value);
                    }
                }
                finally
                {
                    playerListLock.ExitReadLock();
                }
            }

            return tmpPlayerList;
        }

        /// <summary>
        /// 根据玩家Id获取玩家对象
        /// </summary>
        /// <param name="playerId">玩家Id</param>
        /// <returns>玩家对象</returns>
        public Player GetPlayerFromId(Int32 playerId)
        {
            Player player;
            GetPlayerList().TryGetValue(playerId, out player);

            return player;
        }

        /// <summary>
        /// 添加一个玩家
        /// </summary>
        /// <param name="playerId">玩家Id</param>
        /// <param name="pl">玩家对象</param>
        public void Add(Int32 playerId, Player pl)
        {
            // 获取读取锁
            playerListLock.EnterUpgradeableReadLock();

            try
            {
                //玩家是否已存在
                Boolean isContain = playerList.ContainsKey(playerId);

                // 获取写入锁
                playerListLock.EnterWriteLock();

                try
                {
                    // 将玩家添加或刷新到玩家列表和数据库中
                    if (!isContain)
                    {
                        playerList.Add(playerId, pl);
                        playerDB.Add(playerId, pl.PlayerName, pl.PlayerScores);
                    }
                    else
                    {
                        playerDB.Update(playerId, pl.PlayerScores);
                    }
                }
                catch (Exception e)
                {
                    errorMessage = String.Format("[添加玩家{0}失败]:{1}", playerId.ToString(), e.Message);
                    throw new Exception(errorMessage);
                }
                finally
                {
                    playerListLock.ExitWriteLock();
                }
            }
            catch (Exception e)
            {
                errorMessage = String.Format("[操作失败]:{0}", e.Message);
                throw new Exception(errorMessage);
            }
            finally
            {
                playerListLock.ExitUpgradeableReadLock();
            }
        }

        /// <summary>
        /// 通过玩家Id获取玩家积分
        /// </summary>
        /// <param name="playerId">玩家Id</param>
        /// <returns>玩家积分</returns>
        public Int32 GetScoreFromId(Int32 playerId)
        {
            Player player = GetPlayerFromId(playerId);
            if (player != null)
            {
                return player.PlayerScores;
            }

            return 0;
        }

        #endregion

        #region 玩家数据库相关

        private class PlayerDB : DataBase
        {
            /// <summary>
            /// 插入语句
            /// </summary>
            private static String insertStr = @"insert into Player 
                (PlayerId,PlayerName,PlayerScore) 
                values({0},'{1}',{2});";

            /// <summary>
            /// 更新语句
            /// </summary>
            private static String updateStr = "update Player set PlayerScore = {0} where PlayerId = {1};";

            /// <summary>
            /// 查询语句
            /// </summary>
            private static String selectStr = "select * from Player;";

            /// <summary>
            /// 添加玩家到数据库中
            /// </summary>
            /// <param name="playerId">玩家Id</param>
            /// <param name="playerName">玩家姓名</param>
            /// <param name="playerScores">玩家积分</param>
            public void Add(Int32 playerId, String playerName, Int32 playerScores)
            {
                string sql = string.Format(insertStr, playerId, playerName, playerScores);
                ExecuteNotQuery(sql);
            }

            /// <summary>
            /// 更新数据库中的数据
            /// </summary>
            /// <param name="playerId">玩家Id</param>
            /// <param name="playerScores">玩家积分</param>
            public void Update(Int32 playerId, Int32 playerScores)
            {
                string sql = string.Format(updateStr, playerScores, playerId);
                ExecuteNotQuery(sql);
            }

            /// <summary>
            /// 从数据库中加载数据
            /// </summary>
            /// <returns>数据库中的数据</returns>
            public Dictionary<Int32, Player> GetList()
            {
                Dictionary<Int32, Player> list = new Dictionary<Int32, Player>();

                // 从数据库中读取数据
                MySqlDataReader reader = ExecuteQuery(selectStr);
                if (reader != null)
                {
                    while (reader.Read())
                    {
                        Int32 playerId = Convert.ToInt32(reader["PlayerId"]);
                        String playerName = reader["PlayerName"] == null ? "" : reader["PlayerName"].ToString();
                        Int32 playerScores = Convert.ToInt32(reader["PlayerScore"]);

                        list.Add(playerId, new Player(playerId, playerName, playerScores));
                    }
                }

                return list;
            }
        }

        #endregion
    }
}
